﻿namespace Home.Services.SecurityService
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Security.Principal;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Http;
    using System.Web.Http.Dispatcher;
    using System.Web.OData;
    using System.Web.OData.Builder;
    using System.Web.OData.Extensions;
    using Home.Configuration;
    using Owin;

    public static class SecurityServiceHelper
    {
        public static class RoleConstants
        {
            public const string Employee = "Employee";
            public const string Manager = "Manager";
            public const string Administrator = "Administrator";
        }

        public const int MinPasswordLength = 6;
        public const int MaxPasswordLength = 32;

        public static int CompareRole(this IPrincipal principal, Role role)
        {
            Debug.Assert(principal != null);
            Debug.Assert(Enum.IsDefined(typeof(Role), role));

            if (principal.IsInRole(RoleConstants.Employee))
            {
                switch (role)
                {
                    case Role.Employee: return 0;
                    case Role.Manager: return -1;
                    case Role.Administrator: return -1;
                }
            }
            else if (principal.IsInRole(RoleConstants.Manager))
            {
                switch (role)
                {
                    case Role.Employee: return 1;
                    case Role.Manager: return 0;
                    case Role.Administrator: return -1;
                }
            }
            else if (principal.IsInRole(RoleConstants.Administrator))
            {
                switch (role)
                {
                    case Role.Employee: return 1;
                    case Role.Manager: return 1;
                    case Role.Administrator: return 0;
                }
            }

            return -1;
        }

        public static string GetDefaultPassword(this User user)
        {
            Debug.Assert(user != null);
            Debug.Assert(!string.IsNullOrWhiteSpace(user.LoginName));

            return user.LoginName + "@1234";
        }

        public static void ConfigureSecurityService(this IAppBuilder app)
        {
            Debug.Assert(app != null);

            //// build EDM model

            var builder = new ODataConventionModelBuilder()
            {
                Namespace = typeof(UsersController).Namespace,
                ContainerName = "DefaultContainer"
            };

            builder.EnumType<Role>();
            builder.ComplexType<Password>();

            {
                var type = builder.EntitySet<User>("Users").EntityType;
                type.Ignore(c => c._Password);

                {
                    var action = type.Action("ChangePassword");
                    action.Parameter<string>("old");
                    action.Parameter<string>("new");
                }

                {
                    var action = type.Action("UpdatePassword");
                    action.Parameter<string>("new");
                }

                {
                    var function = type.Function("GetPassword");
                    function.Returns<Password>();
                }
            }

            var edmModel = builder.GetEdmModel();

            //// configure web API

            var config = new HttpConfiguration();
            if (!ConfigurationHelper.IsProductionEnvironment)
            {
                config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
            }
            config.MessageHandlers.Add(new ETagMessageHandler());
            config.MapODataServiceRoute("SecurityService", "securityservice", edmModel);
            config.Services.Replace(typeof(IHttpControllerSelector), new NamespaceAwareHttpControllerSelector(config, typeof(UsersController)));
            config.EnsureInitialized();

            app.UseWebApi(config);
        }
    }
}
